home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / program / firstbas.zip / HANOI.BAS < prev    next >
BASIC Source File  |  1996-08-01  |  7KB  |  183 lines

  1. '┌───────────────────────────────────────────────────────────────────────────┐
  2. '│   This  program demostrates a recursive version of the popular "Towers    │
  3. '│ of Hanoi" game.                                                           │
  4. '│                                                                           │
  5. '│  In order to run this program do the following:                           │
  6. '│    1. Load FirstBasic by typing FB at the DOS prompt.                     │
  7. '│    2. Load the file HANOI.BAS from the Load option of the File            │
  8. '│       pulldown menu.                                                      │
  9. '│    3. Compile and run the program by pressing F9.                         │
  10. '└───────────────────────────────────────────────────────────────────────────┘
  11.  
  12. $STACK 32766 ' allocate plenty of stack space since it's a recursive program
  13.  
  14. %X  = 1   ' named constants used for indexing and screen positioning
  15. %Y  = 0
  16. %PromptLine = 24   ' named constant indicating line for all user prompts
  17. %MaxDisks   = 13   ' named constant indicating maximum number of disks
  18. %CursorOff  = 0
  19.  
  20. ' global variable declarations
  21. DIM NumberOfDisks%(1:%MaxDisks + 1), SourceTower%(1:%MaxDisks + 1)
  22. DIM TargetTower%(1:%MaxDisks + 1), Disk$(1:%MaxDisks + 1)
  23. DIM DisksPosition%(%MaxDisks,1), TowerHeight%(1:3)
  24.  
  25. NumberOfMoves% = 0               ' used to keep track of number of moves made
  26. BottomLine%    = 24              ' used to indicate bottom line of display
  27. TowerBase%     = 2
  28.  
  29. SUB Init   ' This procedure is used to initialize the screen and get the number
  30.            ' of disks to use.
  31.   SHARED NumberOfDisks%(), TowerBase%  ' indicate which global vars we need
  32.   LOCAL C%                                ' declare a local variable
  33.  
  34.   KEY OFF                                 ' turn key display off
  35.   COLOR 7, 0                              ' initialize screen color
  36.   CLS
  37.   COLOR 4, 0
  38.   LOCATE 1, 26, %CursorOff
  39.   PRINT "TOWERS OF HANOI"                 ' display the program banner
  40.   COLOR 6, 0
  41.   LOCATE %PromptLine, %X, %CursorOff
  42.   PRINT "Number of Disks (1 TO " + STR$(%MaxDisks) +  ") ";
  43.   DO   ' get the number of disks from the user
  44.     LOCATE %PromptLine, LEN("Number of Disks (1 TO " + STR$(%MaxDisks) +  ") ") + 1, %CursorOff
  45.     INPUT NumberOfDisks%(1)
  46.     IF NumberOfDisks%(1) > %MaxDisks THEN BEEP
  47.   LOOP UNTIL NumberOfDisks%(1) <= %MaxDisks
  48.   TowerBase% = TowerBase% + NumberOfDisks%(1)
  49.   COLOR 7, 0
  50.   LOCATE %PromptLine, %X, %CursorOff
  51.   PRINT SPACE$(79)                        ' clear prompt line
  52. END SUB  ' end procedure Init
  53.  
  54.  
  55. SUB DisplayGameScreen  ' This procedure displays a message on the screen
  56.   SHARED NumberOfDisks%(), TowerBase%   ' indicate which global vars we need
  57.  
  58.   LOCATE 1, 26, %CursorOff              ' position the cursor and turn it on
  59.   COLOR 4, 0                            ' set the display color
  60.   PRINT "TOWERS OF HANOI FOR" NumberOfDisks%(1) "DISKS"
  61.   LOCATE TowerBase% + 1, %X, %CursorOff   ' position the cursor
  62.   COLOR 1, 0                              ' set the display color
  63.   PRINT STRING$(80,176);                  ' display a bar on the screen
  64.   COLOR 7,0                               ' set the display color
  65. END SUB  ' end procedure DisplayGameScreen
  66.  
  67.  
  68. Sub MakeMoves(NumMoves%)
  69.   ' specify the global variables we need
  70.   SHARED RecursionDepth%, NumberOfDisks%(), SourceTower%()
  71.   SHARED TargetTower%(), TowerHeight%()
  72.   ' increment level of recursion
  73.   INCR RecursionDepth%
  74.  
  75.   ' check if we should exit routine
  76.   IF NumberOfDisks%(RecursionDepth%) = 0 THEN
  77.     DECR RecursionDepth%
  78.     EXIT SUB
  79.   END IF
  80.  
  81.   NumberOfDisks%(RecursionDepth% + 1) = NumberOfDisks%(RecursionDepth%) - 1
  82.   SourceTower%(RecursionDepth% + 1) = SourceTower%(RecursionDepth%)
  83.   TargetTower%(RecursionDepth% + 1) = 6 - _
  84.        SourceTower%(RecursionDepth%) - TargetTower%(RecursionDepth%)
  85.   CALL MakeMoves(NumMoves%)
  86.  
  87.   INCR NumMoves%
  88.   CALL DisplayMove
  89.   NumberOfDisks%(RecursionDepth% + 1) = NumberOfDisks%(RecursionDepth%) - 1
  90.   SourceTower%(RecursionDepth% + 1) = 6 - _
  91.         SourceTower%(RecursionDepth%) - TargetTower%(RecursionDepth%)
  92.   TargetTower%(RecursionDepth% + 1) = TargetTower%(RecursionDepth%)
  93.   CALL MakeMoves(NumMoves%)
  94.   DECR RecursionDepth%
  95. END SUB ' end procedure MakeMoves
  96.  
  97.  
  98. SUB DisplayMove
  99.   ' specify the global variables we need
  100.   SHARED Column%, RecursionDepth%, NumberOfDisks%(), SourceTower%()
  101.   SHARED TowerHeight%(), DisksPosition%()
  102.   SHARED TargetTower%(), Disk$()
  103.  
  104.   ' based on current tower, set display column
  105.   IF TargetTower%(RecursionDepth%) = 1 THEN
  106.     Column% = 1
  107.   ELSEIF TargetTower%(RecursionDepth%) = 2 THEN
  108.     Column% = 27
  109.   ELSEIF TargetTower%(RecursionDepth%) = 3 THEN
  110.     Column% = 54
  111.   END IF
  112.  
  113.   ' go to the position of the next disk to move
  114.   LOCATE DisksPosition%(NumberOfDisks%(RecursionDepth%),%Y), _
  115.          DisksPosition%(NumberOfDisks%(RecursionDepth%),%X), %CursorOff
  116.   COLOR 7,0
  117.   PRINT SPACE$(26)      ' erase current disk
  118.  
  119.   ' increment the height of the tower the disk is moving to
  120.   INCR TowerHeight%(SourceTower%(RecursionDepth%))
  121.  
  122.   ' position cursor at top of destination tower
  123.   LOCATE TowerHeight%(TargetTower%(RecursionDepth%)), Column%, %CursorOff
  124.  
  125.   ' get the color
  126.   COLOR NumberOfDisks%(RecursionDepth%) MOD 14 + 1,0
  127.   PRINT Disk$(NumberOfDisks%(RecursionDepth%));   ' display the disk
  128.  
  129.   COLOR 7,0
  130.  
  131.   ' update the current position of this disk
  132.   DisksPosition%(NumberOfDisks%(RecursionDepth%),%Y) = _
  133.                                    TowerHeight%(TargetTower%(RecursionDepth%))
  134.   DisksPosition%(NumberOfDisks%(RecursionDepth%),%X) = Column%
  135.  
  136.   ' decrement the height of the tower the disk came from
  137.   TowerHeight%(TargetTower%(RecursionDepth%)) = _
  138.                                TowerHeight%(TargetTower%(RecursionDepth%)) - 1
  139. END SUB ' end procedure DisplayMove
  140.  
  141.  
  142. ' start of main program
  143. CALL Init
  144.  
  145. ' initialize the array of disks
  146. FOR X% = 1 TO NumberOfDisks%(1)        ' for the number of disks
  147.   Disk$(X%) = STRING$(26,32)  ' fill the array with spaces
  148.   ' put the correct size disk in the array element
  149.   ' 219  ( █ ) is character used to make disks
  150.   MID$(Disk$(X%), %MaxDisks + 1 - X%, X% * 2 - 1) = STRING$(30,219)
  151. NEXT X%
  152.  
  153. ' display the initial disks
  154. Top% = TowerBase% - NumberOfDisks%(1)
  155. FOR X% = 1 TO NumberOfDisks%(1)
  156.   DisksPosition%(X%,%Y) = Top% + X%      ' assign row display
  157.   DisksPosition%(X%,%X) = 1              ' assign column display
  158.   LOCATE Top% + X%, 1, %CursorOff' position cursor
  159.   COLOR X% MOD 14 + 1,0       ' change color
  160.   PRINT Disk$(X%);            ' display the current disk
  161. NEXT X%
  162.  
  163. CALL DisplayGameScreen         ' display game screen
  164.  
  165. TowerHeight%(1) = Top%              ' initialize global variables
  166. TowerHeight%(2) = TowerBase%
  167. TowerHeight%(3) = TowerBase%
  168. SourceTower%(1) = 1
  169. TargetTower%(1) = 3
  170. RecursionDepth% = 0
  171.  
  172. LOCATE 1, 1, %CursorOff : PRINT "Start time: " TIME$
  173.  
  174. CALL MakeMoves(NumberOfMoves%) ' start game
  175.  
  176. LOCATE 2, 1, %CursorOff : PRINT "Stop time : " TIME$
  177.  
  178. LOCATE %PromptLine, 26, %CursorOff
  179. PRINT "DONE IN" NumberOfMoves% "MOVES";
  180.  
  181. END  ' end of program
  182.  
  183.